package com.google.gwt.gwtpages.client.message;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.gwtpages.client.GWTPagesSettings;
import com.google.gwt.gwtpages.client.event.MessageChangeEvent;
import com.google.gwt.user.client.ui.Focusable;

/**
 * Controller class for application notification messages. All messages must
 * implement the {@link GWTMessage} interface. In most cases, you can use
 * {@link SimpleMessage} as the standard implementation.
 * 
 * @author Joe Hudson
 */
public class GWTMessages {

	private static GWTMessages instance;

	protected GWTPagesSettings settings;

	private List<GWTMessage> messages = new ArrayList<GWTMessage>();

	public static GWTMessages get() {
		if (null == instance) instance = new GWTMessages(GWTPagesSettings.get());
		return instance;
	}

	public GWTMessages(GWTPagesSettings settings) {
		if (null == settings)
			throw new IllegalArgumentException("The settings are null");
		this.settings = settings;
		if (null == instance)
			instance = this;
	}

	public GWTMessages() {
		settings = GWTPagesSettings.get();
		if (null == instance)
			instance = this;
	}

	/**
	 * Clear all application messages and fire the {@link MessageChangeEvent}
	 * event
	 */
	public void clear() {
		messages.clear();
		fireChangeEvent();
	}

	/**
	 * Erase any existing messages and set the new messages. Then fire the
	 * {@link MessageChangeEvent} event
	 */
	public void setMessage(GWTMessage... message) {
		messages.clear();
		add(message);
	}

	/**
	 * Erase any existing messages and set the new messages. Then fire the
	 * {@link MessageChangeEvent} event
	 */
	public void setMessages(List<GWTMessage> messages) {
		this.messages.clear();
		this.messages.addAll(messages);
		fireChangeEvent();
	}

	/**
	 * Add the new messages but do not clear the existing messages. Then fire
	 * the {@link MessageChangeEvent} event
	 */
	public void add(GWTMessage... message) {
		for (GWTMessage _message : message) {
			messages.add(_message);
		}
		fireChangeEvent();
	}

	/**
	 * Auto-set a success message. Then fire the {@link MessageChangeEvent}
	 * event
	 * 
	 * @param message
	 *            the message text
	 */
	public void success(String message) {
		setMessage(GWTMessage.success(message));
	}

	/**
	 * Auto-set an error message. Then fire the {@link MessageChangeEvent} event
	 * 
	 * @param message
	 *            the message text
	 */
	public void error(String message, Focusable component) {
		setMessage(GWTMessage.error(message, component));
	}

	private void fireChangeEvent() {
		settings.getEventBus().fireEvent(new MessageChangeEvent(messages));
	}

	/**
	 * Interface defining a container for messages which can be attached to a request seesion for example
	 * 
	 * @author Joe Hudson
	 */
	public interface Data {
		public List<GWTMessage> getMessages();
	}
}